package com.xebia.lightning.scheduler;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Tweet;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;

import com.twitter.Extractor;
import com.xebia.lightning.service.TweetService;

//@Component
public class JobTweetsArchiver {

    private Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private TweetService tweetService;

    static {
        ConfigurationBuilder builder = new ConfigurationBuilder()
                .setDebugEnabled(true)
                .setOAuthConsumerKey("D5QsM4lVmWaY71FAje5yA")
                .setOAuthConsumerSecret(
                        "XcumieVWKz466he7Fi9BgeowyQKC4yTxEj9IXRFFg")
                .setOAuthAccessToken(
                        "66993334-1Q3bdTQuhygGHNeNUgdmtJEjP5grTAsrIemZ8ku7T")
                .setOAuthAccessTokenSecret(
                        "XTNQdVaPfdFcQq6E30WHX6E69j5Ke3gVeU3va7brOYc");
    }

    private final static String[] searchTerms = { "india #jobs",
            "gurgaon #jobs", "delhi #jobs", "noida #jobs", "banglore #jobs",
            "mumbai #jobs", "kolkata #jobs", "pune #jobs", "hyderabad #jobs",
            "chennai #jobs",
    };

    long count = 0;

    @Scheduled(fixedRate = 180000l)
    public void acrhiveJobTweets() throws Exception {
        count++;
        logger.info("Running Archiving Tweets for Job ... " + count);
        TwitterFactory twitterFactory = new TwitterFactory();
        Twitter twitter = twitterFactory.getInstance();
        for (String searchTerm : searchTerms) {
            List<Tweet> tweets = makeTwitterSearch(twitter, searchTerm);
            logger.info("Found tweets before filtering ... " + tweets.size());

            List<Tweet> filteredTweets = filterTweets(tweets);
            logger.info("Found tweets after filtering ... "
                    + filteredTweets.size());

            for (Tweet tweet : filteredTweets) {
                String text = tweet.getText();
                boolean unique = isTweetUnique(text);
                if (!unique) {
                    continue;
                }

                String[] urls = extractUrls(text);
                com.xebia.lightning.domain.Tweet domainTweet = new com.xebia.lightning.domain.Tweet();
                domainTweet.setCreationDate(tweet.getCreatedAt());
                domainTweet.setLocation(tweet.getLocation());
                domainTweet.setText(text);
                domainTweet.setTweetId(tweet.getId());
                domainTweet.setPersitedDate(new Date());
                domainTweet.setLinks(urls);
                tweetService.saveTweet(domainTweet);
            }
        }
    }

    private String[] extractUrls(String text) {
        Extractor extractor = new Extractor();
        List<String> urls = extractor.extractURLs(text);
        List<String> shortenedUrls = new ArrayList<String>();
        for (String url : urls) {
            String resolvedUrl = null;
            try {
                resolvedUrl = resolveShortenedUrl(url);
            } catch (Exception e) {
                logger.warn("Unable to resolve shorted url : " + url, e);
                continue;
            }
            shortenedUrls.add(resolvedUrl);
        }
        return shortenedUrls.toArray(new String[] {});
    }

    private String resolveShortenedUrl(String location) throws Exception {
        HttpURLConnection connection = (HttpURLConnection) new URL(location).openConnection();
        connection.setInstanceFollowRedirects(false);
        while (connection.getResponseCode() / 100 == 3) {
            location = connection.getHeaderField("location");
            connection = (HttpURLConnection) new URL(location).openConnection();
            connection.setInstanceFollowRedirects(false);
        }
        System.out.println(location);
        return location;
    }

    private boolean isTweetUnique(String text) {
        Extractor extractor = new Extractor();
        List<String> urls = extractor.extractURLs(text);
        List<com.xebia.lightning.domain.Tweet> tweets = tweetService.findAllTweetsForLinks(urls.get(0));
        if (CollectionUtils.isEmpty(tweets)) {
            return true;
        }
        return false;
    }

    private List<Tweet> makeTwitterSearch(Twitter twitter, String searchTerm) throws TwitterException {
        logger.info("Quering for search term '" + searchTerm + "'");
        Query query = new Query();
        query.setRpp(100);
        query.setQuery(searchTerm);
        QueryResult queryResult = twitter.search(query);
        List<Tweet> tweets = queryResult.getTweets();
        return tweets;
    }

    private List<Tweet> filterTweets(List<Tweet> tweets) {
        List<Tweet> filteredTweets = new ArrayList<Tweet>();
        for (Tweet tweet : tweets) {
            List<com.xebia.lightning.domain.Tweet> foundTweets = tweetService
                    .findAllTweetsByTweetId(tweet.getId());
            if (!CollectionUtils.isEmpty(foundTweets)) {
                continue;
            }
            filteredTweets.add(tweet);
        }
        return filteredTweets;
    }

    public static void main(String[] args) {
        Twitter twitter = new TwitterFactory().getInstance();
        try {
            String searchTerm = "jobs near:\"san francisco\"";
            QueryResult result = twitter.search(new Query(searchTerm));
            List<Tweet> tweets = result.getTweets();
            for (Tweet tweet : tweets) {
                System.out.println("@" + tweet.getFromUser() + " - " + tweet.getText());
            }
        } catch (TwitterException te) {
            te.printStackTrace();
            System.out.println("Failed to search tweets: " + te.getMessage());
        }
    }

}
